from io import BytesIO
from pathlib import Path
import paramiko
import requests
from requests import Response
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Logger import Logger
from yat.test import macro


class DataMigrationApi:
    def __init__(self, token):
        self.headers = None
        self.log = Logger()
        self.comm_sh = CommonSH()
        self.token = token
        self.ip = f"https://{macro.DATAKIT_HOST}:{macro.DATAKIT_PORT}"

    def get_data_migration_resource(self, db_type: str = '') -> Response:
        """
        获取源端或目标端数据库列表
        :param db_type: 数据库类型（sourceClusters/targetClusters）
        :return:
        """
        api = f'/plugins/data-migration/resource/{db_type}'
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_transcribeReplay_save(self, data: dict) -> Response:
        """
        创建录制回放任务
        :param data: 录制回放任务信息
        :return: 响应结果包含录制回放任务id
        """
        api = '/plugins/data-migration/transcribeReplay/save'
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.post(url=url, json=data, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_transcribeReplay_downloadAndConfig(self, task_id: int, data: dict) -> Response:
        """
        配置录制回放任务并下载录制回放工具
        :param task_id: 任务id
        :param data: 配置信息
        :return:
        """
        api = f"/plugins/data-migration/transcribeReplay/downloadAndConfig?id={task_id}"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.post(url=url, json=data, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_transcribeReplay_list(self, page_num: int = 1, page_size: int = 10,
                                                         task_name: str = None, execution_status: str = None,
                                                         task_start_time: str = None,
                                                         task_end_time: str = None) -> Response:
        """
        查看/刷新录制回放任务列表
        :param page_num: 页数
        :param page_size: 每页最大任务数
        :param task_name: 任务名
        :param execution_status: 任务状态
        :param task_start_time: 任务启动时间
        :param task_end_time: 任务结束时间
        :return:
        """
        api = f"/plugins/data-migration/transcribeReplay/list?pageNum={page_num}&pageSize={page_size}"
        if task_name is not None:
            api += f'&taskName={task_name}'
        if execution_status is not None:
            api += f'&executionStatus={execution_status}'
        if task_start_time is not None:
            api += f'&taskStartTime={task_start_time}'
        if task_end_time is not None:
            api += f"&taskEndTime={task_end_time}"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_transcribeReplay_start(self, task_id: int):
        """
        启动录制回放任务
        :param task_id: 任务id
        :return:
        """
        api = f"/plugins/data-migration/transcribeReplay/start/{task_id}"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        requests.post(url=url, headers=self.headers, verify=False)

    def post_plugins_data_migration_transcribeReplay_delete(self, task_id: str) -> Response:
        """
        删除录制回放任务
        :param task_id:任务id，多个任务id以逗号分隔，例如：task_id = "1，2，3"
        :return:
        """
        api = f'/plugins/data-migration/transcribeReplay/delete/{task_id}'
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.post(url=url, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_transcribeReplay_getHostInfo(self, transcribe_task_id: int) -> Response:
        """
        选择录制任务，获取任务信息
        :param transcribe_task_id:录制任务id
        :return: 源端目标端信息
        """
        api = f'/plugins/data-migration/transcribeReplay/getHostInfo/{transcribe_task_id}'
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        url = self.ip + api
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_resource_installPortal(self, host_id: str, data: dict, ssh_host: str = None,
                                                           ssh_username: str = None, ssh_password: str = None,
                                                           files_path: str = None, chunk_size: int = 8192) -> Response:
        """
        安装portal
        :param chunk_size:
        :param host_id: portal安装机器的hostId
        :param data: portal安装信息
        :param ssh_host: 离线安装时，安装包保存的机器ip
        :param ssh_username: 离线安装时，安装包保存机器的用户
        :param ssh_password: 离线安装时，安装包保存机器的用户的密码
        :param files_path: 离线安装时，安装包路径
        :return:
        """
        api = f'/plugins/data-migration/resource/installPortal/{host_id}'
        url = self.ip + api
        self.headers = {
            "Authorization": "Bearer " + self.token
        }
        if data['installType'] == 1:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(ssh_host, username=ssh_username, password=ssh_password)

            sftp = ssh.open_sftp()
            file_name = Path(files_path).name
            file_obj = BytesIO()

            with sftp.file(files_path, 'rb') as remote_file:
                for chunk in iter(lambda: remote_file.read(chunk_size), b''):
                    file_obj.write(chunk)
            file_obj.seek(0)
            ssh.close()
            files = {
                'file': (file_name, file_obj, 'application/octet-stream')
            }
            response = requests.post(url=url, headers=self.headers, data=data, files=files, verify=False)
            return response
        else:
            response = requests.post(url=url, headers=self.headers, data=data, verify=False)
            return response

    def delete_plugins_data_migration_resource_deletePortal(self, host_id):
        """
        卸载portal
        :param host_id: portal安装机器的hostId
        :return:
        """
        api = f'/plugins/data-migration/resource/deletePortal/{host_id}?onlyPkg=false'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.delete(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_resource_getHosts(self, data: dict = None, page_num: int = 1,
                                                      page_size: int = 10) -> Response:
        """
        查询迁移工具安装信息
        :param data: 筛选条件
        :param page_num: 页数
        :param page_size: 单页显示信息数量
        :return:
        """
        if data is None:
            data = {
                "ip": None,
                "hostname": None,
                "portalType": None,
                "installStatusList": None
            }
        api = f'/plugins/data-migration/resource/getHosts?pageNum={page_num}&pageSize={page_size}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.post(url=url, headers=self.headers, json=data, verify=False)
        return response

    def post_plugins_data_migration_migration_save(self, data: dict) -> Response:
        """
        创建迁移任务
        :param data: 迁移任务信息
        :return:
        """
        api = f'/plugins/data-migration/migration/save'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.post(url=url, headers=self.headers, json=data, verify=False)
        return response

    def post_plugins_data_migration_migration(self, cmd: str, task_id: int) -> Response:
        """
        操作迁移任务,启动、停止、重置
        :param cmd: 指令（start, finsh, reset）
        :param task_id: 迁移任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/{cmd}/{task_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.post(url=url, headers=self.headers, verify=False)
        return response

    def delete_plugins_data_migration_migration(self, task_id: int) -> Response:
        """
        删除迁移任务
        :param task_id: 迁移任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/{task_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.delete(url=url, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_migration_list(self, page_num: int = 1, page_size: int = 10, task_name: str = None,
                                                  exec_status: str = None, exec_start_time: str = None,
                                                  exec_end_time: str = None, finish_start_time: str = None,
                                                  finish_end_time: str = None) -> Response:
        """
        查询迁移任务列表
        :param finish_end_time: 完成结束时间
        :param finish_start_time: 完成开始时间
        :param exec_end_time: 执行结束时间
        :param exec_start_time: 执行开始时间
        :param exec_status: 执行状态
        :param task_name: 任务名
        :param page_num: 页数
        :param page_size: 单页显示信息数量
        :return:
        """
        name = f'&taskName={task_name}'
        exec_time = f'&execStartTime={exec_start_time}&execEndTime={exec_end_time}'
        finish_time = f'&finishStartTime={finish_start_time}&finishEndTime={finish_end_time}'
        status = f'&execStatus={exec_status}'
        if task_name is None:
            name = ''
        if exec_start_time is None and exec_end_time is None:
            exec_time = ''
        if finish_start_time is None and finish_end_time is None:
            finish_time = ''
        if exec_status is None:
            status = ''
        api = f'/plugins/data-migration/migration/list?pageNum={page_num}&pageSize={page_size}{name}' \
              f'{status}{exec_time}{finish_time}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_migration_subTasks(self, main_task_id: int) -> Response:
        """
        查询任务详情
        :param main_task_id: 主任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/subTasks/{main_task_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_migration_alert_count(self, subtask_id) -> Response:
        """
        查看告警信息
        :param subtask_id: 子任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/alert/count/{subtask_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def get_plugins_data_migration_migration_subTaskInfo(self, subtask_id, wss_id) -> Response:
        """
        将wss连接与迁移任务关联
        :param subtask_id: 子任务id
        :param wss_id: wss连接id
        :return:
        """
        api = f'/plugins/data-migration/migration/subTaskInfo/{subtask_id}/{wss_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.get(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_migration_subTask_stop_incremental(self, subtask_id) -> Response:
        """
        停止增量迁移
        :param subtask_id: 子任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/subTask/stop/incremental/{subtask_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.post(url=url, headers=self.headers, verify=False)
        return response

    def post_plugins_data_migration_migration_subTask_start_reverse(self, subtask_id):
        """
        启动反向迁移
        :param subtask_id: 子任务id
        :return:
        """
        api = f'/plugins/data-migration/migration/subTask/start/reverse/{subtask_id}'
        url = self.ip + api
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + self.token
        }
        response = requests.post(url=url, headers=self.headers, verify=False)
        return response
